#include <iostream>
#include "worker/ImgWriter.h"
#include "lib_json/json.h"
#include "tool/Utility.h"
#include "tool/Proto.h"
#include "mgr/LogMgr.h"
#include "mgr/MsgSender.h"

void ImgWriter::Run() {
	m_thread = std::thread(&ImgWriter::_Run, this);
}

// TODO 需要知道休息时间 尽量不要堆积或者塞满!
void ImgWriter::_Run(){
	while (!m_exit)
	{
		ImgWriteInfo info;
        bool ret = m_imgs.Pop(info);
		// 每次运行都跑完为止
		while(ret)
        {
			// std::chrono::time_point<std::chrono::system_clock> start_time = std::chrono::system_clock::now();		
			switch (info.type)
			{
			case 0:{
					// FFMpeg  2K 大概 50ms
					int width = info.pframe->width;
					int height = info.pframe->height;
					cv::Mat image(height, width, CV_8UC3);
					int cvLinesizes[1];
					cvLinesizes[0] = image.step1();
					SwsContext* conversion = sws_getContext(width, height, (AVPixelFormat) info.pframe->format, width, height, AVPixelFormat::AV_PIX_FMT_BGR24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
					sws_scale(conversion, info.pframe->data, info.pframe->linesize, 0, height, &image.data, cvLinesizes);
					sws_freeContext(conversion);

					std::string url = this->m_output + std::to_string(info.id) + "_" + std::to_string(info.index) +".jpg";
					cv::imwrite(url, image);
					std::string msg = Proto::Pack_10010(info.id, url);
					MsgSender::instance().Push(msg);
					ret = m_imgs.Pop(info);
					image.release();
					av_frame_unref(info.pframe);
					break;
				}
			case 1:{
					// OpenCV版本 大约 40ms 差的不多 至少绝对值上不多
					std::string url = this->m_output + std::to_string(info.id) + "_" + std::to_string(info.index) +".png";
					// 重新设置大小 !!
					cv::resize(info.mat, info.mat, cv::Size(1920, 1080), 0, 0, cv::INTER_NEAREST);
					cv::imwrite(url, info.mat);
					std::string msg = Proto::Pack_10010(info.id, url);
					MsgSender::instance().Push(msg);
					ret = m_imgs.Pop(info);
					break;
				}
			default:
				break;
			}
			// std::chrono::time_point<std::chrono::system_clock> end_time = std::chrono::system_clock::now();
			// std::chrono::milliseconds diff = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
			// LOG_INFO("Use Time: " << diff.count())
        }
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
	}
}

void ImgWriter::Push(const ImgWriteInfo& info){
	m_imgs.Push(info);
}